/*
 Автор: Швейкин Евгений Юрьевич

 Функциональное описание:     
    Модуль выполняет расчет CRC. 

    Name    : CRC 32
    Width   : 32
    Poly    : 04C11DB7 (x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + 
                        + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1)
    Init    : FFFFFFFF
    RevIn   : True
    RevOut  : True
    XorOut  : FFFFFFFF
    
    CRC на выходе модуля имеет задержку 1 такт относительно сигнала записи.
*/
//-----------------------------------------------------------------------------

// *********************** НАЧАЛО МОДУЛЯ ***********************************************************
module crc32_d8
(
    input  logic            init,
    input  logic            clk,
    
    input logic [0:7]       data,       // Данные для расчета, перевернутые
    input logic             wre,        // сигнал записи
    
    output logic [31:0]     crc
);
// ********************** МАКРОСЫ ******************************************************************

//  ********************* КОНСТАНТЫ ****************************************************************
    
//  ********************* ТИПЫ ДАННЫХ **************************************************************

//  ********************* ПЕРЕМЕННЫЕ ***************************************************************
    logic [31:0]        shreg;          // Сдвиговый регистр, в котором получаем xor
    logic [31:0]        crc_src;
// ********************* INITIAL *******************************************************************

//  ********************* ФУНКЦИИ ******************************************************************

//  ********************* ASSIGN *******************************************************************

// ********************* ПРОЦЕССЫ ******************************************************************

  always_comb 
  begin
    shreg[0] = data[6] ^ data[0] ^ crc_src[24] ^ crc_src[30];
    shreg[1] = data[7] ^ data[6] ^ data[1] ^ data[0] ^ crc_src[24] ^ crc_src[25] ^ crc_src[30] ^ crc_src[31];
    shreg[2] = data[7] ^ data[6] ^ data[2] ^ data[1] ^ data[0] ^ crc_src[24] ^ crc_src[25] ^ crc_src[26] ^ crc_src[30] ^ crc_src[31];
    shreg[3] = data[7] ^ data[3] ^ data[2] ^ data[1] ^ crc_src[25] ^ crc_src[26] ^ crc_src[27] ^ crc_src[31];
    shreg[4] = data[6] ^ data[4] ^ data[3] ^ data[2] ^ data[0] ^ crc_src[24] ^ crc_src[26] ^ crc_src[27] ^ crc_src[28] ^ crc_src[30];
    shreg[5] = data[7] ^ data[6] ^ data[5] ^ data[4] ^ data[3] ^ data[1] ^ data[0] ^ crc_src[24] ^ crc_src[25] ^ crc_src[27] ^ crc_src[28] ^ crc_src[29] ^ crc_src[30] ^ crc_src[31];
    shreg[6] = data[7] ^ data[6] ^ data[5] ^ data[4] ^ data[2] ^ data[1] ^ crc_src[25] ^ crc_src[26] ^ crc_src[28] ^ crc_src[29] ^ crc_src[30] ^ crc_src[31];
    shreg[7] = data[7] ^ data[5] ^ data[3] ^ data[2] ^ data[0] ^ crc_src[24] ^ crc_src[26] ^ crc_src[27] ^ crc_src[29] ^ crc_src[31];
    shreg[8] = data[4] ^ data[3] ^ data[1] ^ data[0] ^ crc_src[0] ^ crc_src[24] ^ crc_src[25] ^ crc_src[27] ^ crc_src[28];
    shreg[9] = data[5] ^ data[4] ^ data[2] ^ data[1] ^ crc_src[1] ^ crc_src[25] ^ crc_src[26] ^ crc_src[28] ^ crc_src[29];
    shreg[10] = data[5] ^ data[3] ^ data[2] ^ data[0] ^ crc_src[2] ^ crc_src[24] ^ crc_src[26] ^ crc_src[27] ^ crc_src[29];
    shreg[11] = data[4] ^ data[3] ^ data[1] ^ data[0] ^ crc_src[3] ^ crc_src[24] ^ crc_src[25] ^ crc_src[27] ^ crc_src[28];
    shreg[12] = data[6] ^ data[5] ^ data[4] ^ data[2] ^ data[1] ^ data[0] ^ crc_src[4] ^ crc_src[24] ^ crc_src[25] ^ crc_src[26] ^ crc_src[28] ^ crc_src[29] ^ crc_src[30];
    shreg[13] = data[7] ^ data[6] ^ data[5] ^ data[3] ^ data[2] ^ data[1] ^ crc_src[5] ^ crc_src[25] ^ crc_src[26] ^ crc_src[27] ^ crc_src[29] ^ crc_src[30] ^ crc_src[31];
    shreg[14] = data[7] ^ data[6] ^ data[4] ^ data[3] ^ data[2] ^ crc_src[6] ^ crc_src[26] ^ crc_src[27] ^ crc_src[28] ^ crc_src[30] ^ crc_src[31];
    shreg[15] = data[7] ^ data[5] ^ data[4] ^ data[3] ^ crc_src[7] ^ crc_src[27] ^ crc_src[28] ^ crc_src[29] ^ crc_src[31];
    shreg[16] = data[5] ^ data[4] ^ data[0] ^ crc_src[8] ^ crc_src[24] ^ crc_src[28] ^ crc_src[29];
    shreg[17] = data[6] ^ data[5] ^ data[1] ^ crc_src[9] ^ crc_src[25] ^ crc_src[29] ^ crc_src[30];
    shreg[18] = data[7] ^ data[6] ^ data[2] ^ crc_src[10] ^ crc_src[26] ^ crc_src[30] ^ crc_src[31];
    shreg[19] = data[7] ^ data[3] ^ crc_src[11] ^ crc_src[27] ^ crc_src[31];
    shreg[20] = data[4] ^ crc_src[12] ^ crc_src[28];
    shreg[21] = data[5] ^ crc_src[13] ^ crc_src[29];
    shreg[22] = data[0] ^ crc_src[14] ^ crc_src[24];
    shreg[23] = data[6] ^ data[1] ^ data[0] ^ crc_src[15] ^ crc_src[24] ^ crc_src[25] ^ crc_src[30];
    shreg[24] = data[7] ^ data[2] ^ data[1] ^ crc_src[16] ^ crc_src[25] ^ crc_src[26] ^ crc_src[31];
    shreg[25] = data[3] ^ data[2] ^ crc_src[17] ^ crc_src[26] ^ crc_src[27];
    shreg[26] = data[6] ^ data[4] ^ data[3] ^ data[0] ^ crc_src[18] ^ crc_src[24] ^ crc_src[27] ^ crc_src[28] ^ crc_src[30];
    shreg[27] = data[7] ^ data[5] ^ data[4] ^ data[1] ^ crc_src[19] ^ crc_src[25] ^ crc_src[28] ^ crc_src[29] ^ crc_src[31];
    shreg[28] = data[6] ^ data[5] ^ data[2] ^ crc_src[20] ^ crc_src[26] ^ crc_src[29] ^ crc_src[30];
    shreg[29] = data[7] ^ data[6] ^ data[3] ^ crc_src[21] ^ crc_src[27] ^ crc_src[30] ^ crc_src[31];
    shreg[30] = data[7] ^ data[4] ^ crc_src[22] ^ crc_src[28] ^ crc_src[31];
    shreg[31] = data[5] ^ crc_src[23] ^ crc_src[29];
  end

  always_ff @(posedge clk) 
  begin
    if (init) begin
      crc_src   <= {32{1'b1}};
      crc       <= {32{1'b1}};
    end
    else begin
        if (wre) begin
            crc_src <= shreg;
            crc     <= shreg ^ 32'hFF_FF_FF_FF; 
        end
        else;
    end
  end
  
endmodule